<!DOCTYPE html>
<html lang="en">

	<head>
		<meta charset="UTF-8">
		<title>Solar System</title>
		<style type="text/css">
			html,
			body {
				margin: 0;
				height: 100%;
			}

			canvas {
				display: block;
			}
		</style>
	</head>

	<body onload="draw();">

	</body>

	<script src="./js/three.js" type="text/javascript" charset="utf-8"></script>
	<script src="./js/OrbitControls.js"></script>
	<script src="./js/stats.min.js"></script>

	<script>
		var UNITNUM = 100;

		var renderer;

		function initRender() {
			renderer = new THREE.WebGLRenderer({
				antialias: true
			});
			renderer.setSize(window.innerWidth, window.innerHeight);

			//告诉渲染器需要阴影效果
			renderer.shadowMap.enabled = true;

			// 默认的是，没有设置的这个清晰 THREE.PCFShadowMap
			renderer.shadowMap.type = THREE.PCFSoftShadowMap;
			document.body.appendChild(renderer.domElement);
		}


		var camera;

		function initCamera() {
			camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
			camera.position.set(UNITNUM, UNITNUM, UNITNUM);
			camera.lookAt(new THREE.Vector3(0, 0, 0));
		}

		var scene;

		function initScene() {
			scene = new THREE.Scene();
			//给场景设置雾化效果 ，参数(雾的颜色，雾化开始距离相机的 距离，雾化结束距离相机的距离)
			scene.fog = new THREE.Fog(0x0000ff, 200, 700);
		}

		var ambientLight, directionalLight;

		function initLight() {
			//环境光
			ambientLight = new THREE.AmbientLight("#ffffff");
			scene.add(ambientLight);

			//点光源
			spotLight = new THREE.PointLight("#ffffff", 1);
			spotLight.position.set(0, 0.1 * UNITNUM, 0);

			//告诉平行光需要开启阴影投射
			spotLight.castShadow = true;
			scene.add(spotLight);
		}

		var moon, earth, earthPath, plane, earthSys, solarSys;

		function initModel() {
			//辅助工具
			var helper = new THREE.AxesHelper(UNITNUM);
			scene.add(helper);

			//Milky Way
			var sunCube = new THREE.Mesh(new THREE.SphereGeometry(2 * UNITNUM, 0.5 * UNITNUM, 0.5 * UNITNUM),
				new THREE.MeshBasicMaterial({
					map: new THREE.TextureLoader().load("./img/solar.jpg"),
					side: THREE.DoubleSide
				}));
			sunCube.position.set(0, 0, 0);
			scene.add(sunCube);

			//sunCube
			var sphereGeometry = new THREE.SphereGeometry(0.1 * UNITNUM, 3 * UNITNUM, 3 * UNITNUM);
			var sunMap = new THREE.TextureLoader().load("./img/sun.jpg");
			var sphereMaterial = new THREE.MeshBasicMaterial({
				map: sunMap
			})
			var sunCube = new THREE.Mesh(sphereGeometry, sphereMaterial);
			sunCube.position.set(0, 0.1 * UNITNUM, 0);
			scene.add(sunCube);

			//moon
			var cubeGeometry = new THREE.SphereGeometry(0.03 * UNITNUM, 0.5 * UNITNUM, 0.5 * UNITNUM);
			var map = new THREE.TextureLoader().load("./img/moon.jpg");
			cubeMaterial = new THREE.MeshPhongMaterial({
				map: map
			});
			moon = new THREE.Mesh(cubeGeometry, cubeMaterial);
			moon.position.set(0.1 * UNITNUM, 0.1 * UNITNUM, 0);

			//earth
			var cubeGeometry = new THREE.SphereGeometry(0.06 * UNITNUM, 0.5 * UNITNUM, 0.5 * UNITNUM);
			var map = new THREE.TextureLoader().load("./img/earth.jpg");
			cubeMaterial = new THREE.MeshLambertMaterial({
				map: map
			});
			earth = new THREE.Mesh(cubeGeometry, cubeMaterial);
			earth.position.set(0, 10, 0);

			//地球自转轨道
			earthPath = new THREE.Mesh(new THREE.TorusGeometry(0.1 * UNITNUM, 0.001 * UNITNUM, UNITNUM, UNITNUM),
				new THREE.MeshBasicMaterial({
					color: 0xcccccc,
					opacity: 0.2
				})
			);
			earthPath.position.set(0, 0.1 * UNITNUM, 0);
			earthPath.rotation.x = Math.PI * 0.5;


			earthSys = new THREE.Group();
			earthSys.add(earthPath);
			earthSys.add(moon);
			earthSys.add(earth);
			earthSys.position.x = 50;
			earth.rotation.z = 23 * Math.PI / 180;

			solarSys = new THREE.Group();
			solarSys.add(earthSys);
			scene.add(solarSys);

			//轨道
			object = new THREE.Mesh(new THREE.TorusGeometry(0.5 * UNITNUM, 0.1, 1 * UNITNUM, 1 * UNITNUM),
				new THREE.MeshBasicMaterial({
					color: 0xcccccc,
					opacity: 0.2
				})
			);
			object.position.set(0, 0.1 * UNITNUM, 0);
			object.rotation.x = Math.PI * 0.5;
			scene.add(object);

			//告诉立方体需要投射阴影
			moon.castShadow = true;
			earth.castShadow = true;
			//告诉立方体需要接受阴影
			earth.receiveShadow = true;
			moon.receiveShadow = true;

			//底部平面
			// 			var planeGeometry = new THREE.PlaneGeometry(5000, 5000, 200, 20);
			// 
			// 			var planeMaterial = new THREE.MeshPhongMaterial({
			// 				color: 0xaaaaaa
			// 			});
			// 
			// 			plane = new THREE.Mesh(planeGeometry, planeMaterial);
			// 
			// 			plane.rotation.x = -0.5 * Math.PI;
			// 
			// 			plane.position.y = -0;
			// 			plane.receiveShadow = true;
			// 			scene.add(plane);
			//告诉底部平面需要接收阴影

		}

		//初始化性能插件

		var stats;

		function initStats() {
			stats = new Stats();
			document.body.appendChild(stats.dom);

		}

		//用户交互插件 鼠标左键按住旋转，右键按住平移，滚轮缩放
		var controls;

		function initControls() {
			controls = new THREE.OrbitControls(camera, renderer.domElement);

			// 使动画循环使用时阻尼或自转 意思是否有惯性
			controls.enableDamping = true;

			//动态阻尼系数 就是鼠标拖拽旋转灵敏度
			controls.dampingFactor = 0.95;

			//是否可以缩放
			controls.enableZoom = true;

			//是否自动旋转

			controls.autoRotate = false;

			//设置相机距离原点的最近距离
			controls.minDistance = 0.5 * UNITNUM;

			//设置相机距离原点的最远距离
			controls.maxDistance = 1.8 * UNITNUM;

			//是否开启右键拖拽
			controls.enablePan = false;

		}

		function render() {
			renderer.render(scene, camera);
		}

		//窗口变动触发的函数

		function onWindowResize() {

			camera.aspect = window.innerWidth / window.innerHeight;
			// 更改参数的时候 必须使用
			camera.updateProjectionMatrix();

			render();

			renderer.setSize(window.innerWidth, window.innerHeight);

		}

		// 假设每一桢（每一次渲染）是一天，则地球 公转角速度为
		var revolutionV = 1 / 365 * 360 * Math.PI / 180;

		// 放慢速度的比例,方便观察
		var ratio = 0.01;
		revolutionV *= ratio || 1;

		function animate() {
			solarSys.rotation.y += revolutionV;
			earthSys.rotation.y += 26 * revolutionV;
			earth.rotation.y += 365 * revolutionV;
			//更新控制器

			render();

			//更新性能插件
			stats.update();
			controls.update();
			requestAnimationFrame(animate);

		}

		function draw() {

			initRender();

			initScene();

			initCamera();

			initLight();

			initModel();

			initControls();

			initStats();

			animate();

			window.onresize = onWindowResize;

		}
	</script>

</html>
